/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package compiler.grammar;

import compiler.DotDump;
import compiler.antlr.REAST;
import compiler.antlr.RELexer;
import compiler.antlr.REParser;
import compiler.scanner.dfa.DFAGen;
import compiler.scanner.nfa.NFAItem;
import compiler.scanner.nfa.NFAState;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.CommonTreeNodeStream;

/**
 *
 * @author meemo
 */
public class Terminal extends Symbol implements Comparable<Terminal>
{
    //~ Static fields/initializers ---------------------------------------------

    private static int           NEXT_ID = 0; // 1 is reserved for EOF
    public static final Terminal EOF = new Terminal("$");

    //~ Instance fields --------------------------------------------------------

    //private final DFATable dfaTable;
    private final NFAItem nfa;
    private final String  name;
    private final String  reStr;
    private final int     id = nextId();

    //~ Constructors -----------------------------------------------------------

    // only to be called for $ ( the EOF )
    public Terminal(String name)
    {
        this.name  = name;
        this.reStr = "";
        nfa        = null;
    }

    public Terminal(String name, String reStr) throws RecognitionException
    {
        this.name = name;

        if ((reStr.length() > 2) && (reStr.charAt(0) == '"') && (reStr.charAt(reStr.length() - 1) == '"')) // have quotes
        {
            this.reStr = reStr.substring(1, reStr.length() - 1); // remove the "quotes"
        }
        else
            this.reStr = reStr;

        if (reStr.length() > 0)
        {
            System.out.println("Trying to parse RE " + reStr);
            nfa = new REAST(new CommonTreeNodeStream((CommonTree)new REParser(new CommonTokenStream(new RELexer(new ANTLRStringStream(this.reStr)))).start().getTree())).start(name);
//
//            try
//            {
//                PrintWriter      writer;
//                writer = new PrintWriter(new FileOutputStream("../testcases/nfa_" + getName() + ".dot"));
//                writer.println(DotDump.dumpDot(this.nfa.getStartState()));
//                writer.close();
//            } catch (Exception ex)
//            {
//                Logger.getLogger(Terminal.class.getName()).log(Level.SEVERE, null, ex);
//            }
        }
        else
            nfa = null;
    }

    //~ Methods ----------------------------------------------------------------

    public static void reset()
    {
        NEXT_ID = 1; // not to zero cuz 0 is already reserved for EOF
    }

    public int compareTo(Terminal o)
    {
        return this.name.compareTo(o.name); // for prettier output when printing lookaheads
    }

    @Override
    public boolean equals(Object obj)
    {
        if (obj == null)
        {
            return false;
        }

        if (getClass() != obj.getClass())
        {
            return false;
        }

        final Terminal other = (Terminal)obj;

        if ((this.name == null) ? (other.name != null) : (!this.name.equals(other.name)))
        {
            return false;
        }

        return true;
    }

    public int getId()
    {
        return id;
    }

    public NFAState getNFAStart()
    {
        return nfa.getStartState();
    }

    public String getName()
    {
        return name;
    }

    public String getREString()
    {
        return reStr;
    }

    @Override
    public int hashCode()
    {
        return name.hashCode();
    }

    @Override
    public String toString()
    {
        return name;
    }

    protected static synchronized int nextId()
    {
        return NEXT_ID++;
    }
}
